﻿using System;
using System.Windows.Forms;

namespace IA2MazeSolver
{
    public partial class FormInicial : Form
    {
        private Maze Labirinto;
        private MazeSolver Solver;

        public FormInicial()
        {
            InitializeComponent();

            this.DebugStart();

            this.cmbSelecao.Items.Add(new { Value = 0, Nome = "Torneio" });
            this.cmbSelecao.Items.Add(new { Value = 1, Nome = "Roleta" });
            this.cmbSelecao.Items.Add(new { Value = 2, Nome = "Ranking" });

            this.cmbSelecao.DisplayMember = "Nome";
            this.cmbSelecao.ValueMember = "Value";

            //Default
            this.txtPopulacao.Text = "20000";
            this.txtCrossOver.Text = "50";
            this.txtNumeroGeracoes.Text = "20";
            this.txtMutacao.Text = "50";
            this.txtSolucaoAbaixoDe.Text = "1";
            this.cmbSelecao.SelectedIndex = 1;

            this.txtPlotar.Text = "00010100000001010101101010010000000000010100000011000100";

            /* #################################### */
            Individuo indExemplo = MazeHelper.StringToByte("00010100000001010101101010010000000000010100000011000100");
            Labirinto = new Maze();
            Labirinto.RenderTo(this.pnlMaze, indExemplo.Data);
            
            this.Solver = new MazeSolver(Labirinto);

            MazeDebug.Write("Avaliacao: " + this.Solver.AvaliarIndividuo(indExemplo));
            /* #################################### */

            this.DebugRefresh();
        }

        private void btnExecutar_Click(object sender, EventArgs e)
        {
            this.DebugStart();

            int populacao = 0;
            try
            {
                populacao = Convert.ToInt32(txtPopulacao.Text);
            }
            catch (Exception) { }

            int geracoes = 0;
            try
            {
                geracoes = Convert.ToInt32(txtNumeroGeracoes.Text);
            }
            catch (Exception) { }

            int fitness = 0;
            try
            {
                fitness = Convert.ToInt32(txtSolucaoAbaixoDe.Text);
            }
            catch (Exception) { }

            int crossover = 0;
            try
            {
                crossover = Convert.ToInt32(txtCrossOver.Text);
            }
            catch (Exception) { }

            int mutacao = 0;
            try
            {
                mutacao = Convert.ToInt32(txtMutacao.Text);
            }
            catch (Exception) { }

            int tipo = 0;
            try
            {
                var x = this.Cast(cmbSelecao.SelectedItem, new { Value = 0, Nome = "" });
                tipo = x.Value;
            }
            catch (Exception) { }

            this.Labirinto.RenderTo(this.pnlMaze, new byte[] { 0, 0 });
            Individuo menor = this.Solver.Solve(populacao, fitness, geracoes, crossover, mutacao, tipo);
            this.Labirinto.RenderTo(this.pnlMaze, menor.Data);

            this.txtPlotar.Text = String.Join("", menor.Data);

            this.DebugRefresh();
        }

        private T Cast<T>(object obj, T type)
        {
            return (T)obj;
        }

        private void btnPlotar_Click(object sender, EventArgs e)
        {
            this.DebugStart();

            Individuo ind = MazeHelper.StringToByte(txtPlotar.Text);
            this.Solver.AvaliarIndividuo(ind);
            this.Labirinto.RenderTo(this.pnlMaze, ind.Data);

            this.DebugRefresh();
        }

        public void DebugStart()
        {
            MazeDebug.Clear();
            MazeDebug.Melhor = this.cbxDebugMelhor.Checked;
            MazeDebug.Avaliacao = this.cbxDebugAvaliacao.Checked;
            MazeDebug.Geracao = this.cbxDebugGeracoes.Checked;
        }

        public void DebugRefresh()
        {
            this.txtDebug.Text = MazeDebug.toString();
            this.txtDebug.SelectionStart = this.txtDebug.Text.Length;
            this.txtDebug.ScrollToCaret();
            this.txtDebug.Refresh();
        }

        private void btnDebugClear_Click(object sender, EventArgs e)
        {
            this.txtDebug.Clear();
        }

        private void txtDebug_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.A)
            {
                txtDebug.SelectAll();
            }
        }
    }
}
